%--------------------------------------------------------------------------
%   CDMA通信系统仿真学习
%--------------------------------------------------------------------------
clear;clc;
%--------------------------------------------------------------------------
%   产生发射的内容数据
%--------------------------------------------------------------------------
data = randi([0 1],1,15);                                                   %编码发生器
data_exp = ones(1,64)'*data;
data_exp = 2*data_exp(:) - 1;                                               %编码延长
figure(1)
subplot(421)
plot(data_exp)
axis([1,15*64,-2,2]);title('发射内容')
%--------------------------------------------------------------------------
%   查看码型的单边谱
%--------------------------------------------------------------------------
data_f = fft(data_exp);
subplot(422)
plot(abs(data_f(1:(15*32))))
title('码型频谱')

%--------------------------------------------------------------------------
%   然后我们选择沃尔什编码中的一个，并使用它来传播我们的数据。扩展过程只需要
%   将数据行代码乘以更高的速率扩展代码(这里的扩展代码是数据速率的64倍)。
%   即芯片速率= 64 *数据速率)。
%   产生的信号具有高得多的数据速率——与芯片速率相同。
%--------------------------------------------------------------------------
codes = hadamard(64);                                                       %64*64阿达马矩阵
user_code = codes(:,35);                                                    %取第33列作为用户编码
spread = zeros(1,15*64);
count = 0;

%--------------------------------------------------------------------------
%   将发射的内容 每次都乘以发射的用户编码,64一个码长
%--------------------------------------------------------------------------
for idx = 1:15
	spread((count+1):(count+64)) = data_exp((count+1):(count+64)).*user_code;
	count = count + 64;
end 
subplot(423)
plot(spread)                                                                %加入用户编码的数据
axis([1,15*64,-2,2]);title('加入用户编码')

%--------------------------------------------------------------------------
%   合成的频谱在带宽上比数据信号的频谱宽得多。请注意，下面的代码不能准确地显
%   示扩频信号的频谱。为什么?
%--------------------------------------------------------------------------
spread_f = fft(spread);
subplot(424)
plot(abs(spread_f(1:(15*32))))
title('编码后的频谱')

%--------------------------------------------------------------------------
%   然后，我们可以通过将码波形相乘，并将每64个芯片相加(由于1*1 = 1和-1* -1 = 1，
%   因此将码相乘两次的效果是恢复原始数据序列)，从扩频信号中恢复数据。
%   显然同步是一个问题——我们如何匹配发射机和接收机的代码序列?
%--------------------------------------------------------------------------
%   恢复数据
%--------------------------------------------------------------------------
%   将编码后的数据按照64长对自身相乘,因为完全一样,向量完全相关
%   还原数据->data_desp
%--------------------------------------------------------------------------
count = 0;
for idx = 1:15
 data_desp((count+1):(count+64)) = spread((count+1):(count+64)).*user_code';
 count = count + 64;
end

%--------------------------------------------------------------------------
%   还原后的波形求和,64->1得到原始编码
%--------------------------------------------------------------------------
count = 0;
for idx = 1:15
 data_rec(idx) = sum(data_desp((count+1):(count+64)))/64;
 count = count+64;
end

%--------------------------------------------------------------------------
%   在将其扩展回原来的64长度
%--------------------------------------------------------------------------
data_rec_exp = ones(1,64)'*data_rec;
data_rec_exp = data_rec_exp(:);

subplot(425)
plot(data_rec_exp)
axis([1,15*64,-2,2]);title('还原后的码型')

%--------------------------------------------------------------------------
%   我们可以在CDMA扩频信号中加入噪声，使其在“噪声下限”以下无法区分
%--------------------------------------------------------------------------
noise = 2*randn(1,15*64);                                                   %加入标准差为5的噪声
% noisy_cdma = spread + noise;                                                %发射出去的编码+噪声
noisy_cdma = awgn(spread,-10);                                                %发射出去的编码+噪声
subplot(426)
plot(noisy_cdma);title('对加入用户编码后的信号加入噪声')
axis([1,15*64,-12,12]) 

%--------------------------------------------------------------------------
%   我们可以用同样的方法恢复我们的信号，因为我们的信号和代码高度相关，
%   但是代码和噪声信号是不相关的。编码，但是编码和噪声信号是不相关的。
%--------------------------------------------------------------------------
%   对回波噪声乘以用户码进行解码
%--------------------------------------------------------------------------
count = 0;
for idx = 1:15
    noisy_data_desp((count+1):(count+64)) =...
    noisy_cdma((count+1):(count+64)).*user_code';
    count = count + 64;
end
%--------------------------------------------------------------------------
%   解码后的信号求和,合成一组数据
%--------------------------------------------------------------------------
count = 0;
for idx = 1:15
    noisy_data_rec(idx) = sum(noisy_data_desp((count+1):(count+64)))/64;
    count = count+64;
end
%--------------------------------------------------------------------------
%   二值判决,强制分为0 1
%--------------------------------------------------------------------------
for idx = 1:15
    if (noisy_data_rec(idx) > 0)
        noise_rec(idx) = 1;
    else
        noise_rec(idx) = -1;
    end
end

data_rec_exp = ones(1,64)'*data_rec;
data_rec_exp = data_rec_exp(:);
count = 0;

noisy_data_rec_exp = ones(1,64)'*noise_rec;
noisy_data_rec_exp = noisy_data_rec_exp(:);

subplot(427)
plot(noisy_data_rec_exp);title('还原码型')
axis([1,15*64,-2,2]) 
subplot(428)
plot(abs(noisy_data_rec_exp-data_exp));title('误码')
axis([1,15*64,-2,2])
